package saxion.speelveld.spaceengineer.view;

import java.util.Observable;
import java.util.Observer;

import saxion.speelveld.spaceengineer.GameScreen;
import saxion.speelveld.spaceengineer.buildings.Mines;
import saxion.speelveld.spaceengineer.controller.BitmapManager;
import saxion.speelveld.spaceengineer.model.BuildingTile;
import saxion.speelveld.spaceengineer.model.Game;
import saxion.speelveld.spaceengineer.model.InfrastructureTile;
import saxion.speelveld.spaceengineer.model.ObstacleTile;
import saxion.speelveld.spaceengineer.model.ResourceTile;
import saxion.speelveld.spaceengineer.model.Tile;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class GameField extends View implements Observer
{
	private int tileSize;

	private int tilesInHeight, tilesInWidth;

	private float fingerdownX, fingerdownY;

	private int sparespaceX, sparespaceY;

	private Paint paint;

	private Game game;

	private boolean buildingMode;

	private int buildingPartTouchedX, buildingPartTouchedY;

	private boolean touched = false;

	private Tile[][] fieldtoview;

	public GameField(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
		init();
	}

	public GameField(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		init();
	}

	public GameField(Context context)
	{
		super(context);
		init();
	}

	public void init()
	{
		game = null;
		buildingMode = false;
		// calcTileSize(this.getWidth(), this.getHeight());
		// sparespaceX = (this.getWidth() - (tileSize * tilesInWidth)) / 2;
		// sparespaceY = (this.getHeight() - (tilesInHeight * tileSize)) / 2;
	}

	public void SetGame(Game game)
	{
		this.game = game;
		calcTileSize(this.getWidth(), this.getHeight());
		invalidate();
		game.addObserver(this);
	}

	@Override
	protected void onDraw(Canvas canvas)
	{
		// Date d = Calendar.getInstance().getTime();
		// long startMills = Calendar.getInstance().getTimeInMillis();

		if (this.game == null)
		{
			Log.i("getBitmapFromResources", "stopping ondraw");
			return;
		}

		Log.i("getBitmapFromResources", "starting ondraw");

		// als de tiles nog geen grote hebben eerst berekenen
		if (tileSize == 0)
		{
			calcTileSize(this.getWidth(), this.getHeight());
		}

		sparespaceX = (this.getWidth() - (tileSize * tilesInWidth)) / 2;
		sparespaceY = (this.getHeight() - (tilesInHeight * tileSize)) / 2;
		// Linksonder ->
		// sparespaceX = 0;
		// sparespaceY = (this.getHeight() - (tilesInHeight * tileSize));

		paint = new Paint();
		paint.setColor(Color.BLACK);
		paint.setStrokeWidth(3);

		if (game != null)
		{
			fieldtoview = game.GetFieldToShow(tilesInWidth, tilesInHeight, fieldtoview);

			Log.d("getBitmapFromResources", "start");
			for (int x = 0; x < tilesInWidth; x++)
			{
				for (int y = 0; y < tilesInHeight; y++)
				{
					// TODO has to be the immage of fieldtoview

					// draws the background of the field.

					canvas.drawBitmap(BitmapManager.getScaledBitmapFromResources(fieldtoview[x][y].getBackgroundID(),
						getContext(), tileSize), x * tileSize + sparespaceX, y * tileSize + sparespaceY, paint);

					if (fieldtoview[x][y].getClass().equals(InfrastructureTile.class))
					{
						if (buildingMode || game.isBuildInfrastructure())
						{
							if (((InfrastructureTile) fieldtoview[x][y]).isConnected())
							{
								paint.setColor(Color.argb(100, 255, 255, 0));
								canvas.drawRect((int) (x * tileSize + sparespaceX),
									(int) (y * tileSize + sparespaceY),
									(int) (x
										* tileSize + sparespaceX)
										+ tileSize, (int) (y * tileSize + sparespaceY)
										+ tileSize,
									paint);
								paint.setColor(Color.BLACK);
							}
						}
						canvas.drawBitmap(((InfrastructureTile) fieldtoview[x][y]).getPic(getContext(),
							tileSize),
							x * tileSize + sparespaceX, y * tileSize + sparespaceY, paint);
					}

					if (fieldtoview[x][y].getClass().equals(ResourceTile.class))
					{
						canvas
							.drawBitmap(
								BitmapManager.getTileBackgroundByResourceType(
									((ResourceTile) fieldtoview[x][y]).getResourceType(), getContext(), tileSize,
									tileSize),
								(int) (x * tileSize + sparespaceX),
								(int) (y * tileSize + sparespaceY),
								paint);
					}

					if (fieldtoview[x][y].getClass().equals(ObstacleTile.class))
					{
						canvas.drawBitmap(BitmapManager.getScaledBitmapFromResources(
							((ObstacleTile) fieldtoview[x][y]).getObstaclePicID(), getContext(), tileSize),
							(int) (x * tileSize + sparespaceX),
							(int) (y * tileSize + sparespaceY),
							paint);
					}

					if (fieldtoview[x][y].getClass().equals(BuildingTile.class))
					{
						canvas.drawBitmap(BitmapManager.getScaledBitmapFromResources(
							((BuildingTile) fieldtoview[x][y]).getImageID(), getContext(), tileSize),
							(int) (x * tileSize + sparespaceX),
							(int) (y * tileSize + sparespaceY),
							paint);

						if (buildingMode || game.isBuildInfrastructure())
						{
							if (((BuildingTile) fieldtoview[x][y]).getBuilding().isConnectedToSpaceCenter())
							{
								paint.setColor(Color.argb(100, 255, 255, 0));
								canvas.drawRect((int) (x * tileSize + sparespaceX),
									(int) (y * tileSize + sparespaceY),
									(int) (x
										* tileSize + sparespaceX)
										+ tileSize, (int) (y * tileSize + sparespaceY)
										+ tileSize,
									paint);
								paint.setColor(Color.BLACK);
							}
						}

					}

					// canvas.drawText(x + "," + y, x * tileSize + sparespaceX + 10, y * tileSize + sparespaceY + 20,
					// paint);
				}
			}
			Log.d("getBitmapFromResources", "end");

			if (buildingMode || game.isBuildInfrastructure())
			{
				// tekent het raster.
				paint.setColor(Color.BLACK);
				for (int x = 0; x <= tilesInWidth; x++)
				{
					canvas.drawLine(x * tileSize + sparespaceX, sparespaceY, x * tileSize + sparespaceX, tilesInHeight
						* tileSize + sparespaceY, paint);
				}
				for (int y = 0; y <= tilesInWidth; y++)
				{
					canvas.drawLine(sparespaceX, y * tileSize + sparespaceY, tilesInWidth * tileSize + sparespaceX, y
						* tileSize + sparespaceY, paint);
				}

				// TODO teken Building Ghost
				if (game.getQueuedBuilding() != null)
				{

					for (int x = 0; x < game.getQueuedBuilding().getWidth(); x++)
					{
						for (int y = 0; y < game.getQueuedBuilding().getHeight(); y++)
						{
							if (fieldtoview[game.queuedBuildingX + x][game.queuedBuildingY + y].getClass().equals(
								Tile.class))
							{
								paint.setColor(Color.argb(100, 0, 255, 0));
							}
							else
							{
								if (game.getQueuedBuilding() instanceof Mines
									&& fieldtoview[game.queuedBuildingX + x][game.queuedBuildingY + y].getClass()
										.equals(
											ResourceTile.class))
								{
									paint.setColor(Color.argb(100, 0, 255, 0));
								}
								else
								{
									paint.setColor(Color.argb(100, 255, 0, 0));
								}

							}
							// ehh iets(tekent een vierkantje :)
							canvas.drawRect((int) ((game.queuedBuildingX + x) * tileSize + sparespaceX),
								(int) ((game.queuedBuildingY + y) * tileSize + sparespaceY),
								(int) ((game.queuedBuildingX + x)
									* tileSize + sparespaceX)
									+ tileSize, (int) ((game.queuedBuildingY + y) * tileSize + sparespaceY)
									+ tileSize,
								paint);
						}
					}
				}
				// ghost infrastructure tekenen;
				if (game.isBuildInfrastructure())
				{
					if (fieldtoview[game.queuedBuildingX][game.queuedBuildingY].getClass().equals(
						Tile.class))
					{
						paint.setColor(Color.argb(100, 0, 255, 0));
					}
					else
					{
						paint.setColor(Color.argb(100, 255, 0, 0));
					}
					// ehh iets(tekent een vierkantje :)
					canvas.drawRect((int) (game.queuedBuildingX * tileSize + sparespaceX),
						(int) (game.queuedBuildingY * tileSize + sparespaceY),
						(int) (game.queuedBuildingX * tileSize + sparespaceX)
							+ tileSize, (int) (game.queuedBuildingY * tileSize + sparespaceY)
							+ tileSize,
						paint);

				}
			}
		}
		// d = Calendar.getInstance().getTime();
		// long endMills = Calendar.getInstance().getTimeInMillis();
		Log.i("getBitmapFromResources", "ending ondraw");
	}

	public void calcTileSize(int canvasWidth, int canvasHeight)
	{
		DisplayMetrics dm = getResources().getDisplayMetrics();
		double lengthOfCanvas = canvasWidth / dm.xdpi;
		// double heightOfCanvas = canvasHeight / dm.ydpi;
		tileSize = (int) (canvasWidth / (int) (lengthOfCanvas / 0.2));

		// calculate how many blocks fit in the height
		tilesInHeight = canvasHeight / tileSize;
		tilesInWidth = canvasWidth / tileSize;
		game.setTilesOverX(tilesInWidth);
		game.setTilesOverY(tilesInHeight);

	}

	@Override
	public boolean onTouchEvent(MotionEvent e)
	{
		if (e.getAction() == MotionEvent.ACTION_DOWN)
		{
			fingerdownX = e.getX();
			fingerdownY = e.getY();
			if (buildingMode)
			{
				if (!(overFieldX((int) fingerdownX) < game.queuedBuildingX)
					&& !(overFieldX((int) fingerdownX) > game.queuedBuildingX + game.getQueuedBuilding().getWidth()))
				{
					if (!(overFieldY((int) fingerdownY) < game.queuedBuildingY)
						&& !(overFieldY((int) fingerdownY) > game.queuedBuildingY
							+ game.getQueuedBuilding().getHeight()))
					{
						buildingPartTouchedX = overFieldX((int) fingerdownX) - game.queuedBuildingX;
						buildingPartTouchedY = overFieldY((int) fingerdownY) - game.queuedBuildingY;
					}
				}
			}
			else if (game.isBuildInfrastructure() == true)
			{
				if (overFieldX((int) fingerdownX) - game.queuedBuildingX == 0
					&& overFieldY((int) fingerdownY) - game.queuedBuildingY == 0)
				{
					touched = true;
				}

			}
			else
			{

			}
		}

		if (e.getAction() == MotionEvent.ACTION_MOVE)
		{
			if (buildingMode)
			{
				if (buildingPartTouchedX >= 0 && buildingPartTouchedY >= 0)
				{
					if ((overFieldX((int) e.getX()) - buildingPartTouchedX) >= 0
						&& (overFieldY((int) e.getY()) - buildingPartTouchedY) >= 0)
					{
						if (overFieldX((int) e.getX()) - buildingPartTouchedX <= tilesInWidth
							- game.getQueuedBuilding().getWidth()
							&& overFieldY((int) e.getY()) - buildingPartTouchedY <= tilesInHeight
								- game.getQueuedBuilding().getHeight())
						{
							game.queuedBuildingX = (overFieldX((int) e.getX()) - buildingPartTouchedX);
							game.queuedBuildingY = (overFieldY((int) e.getY()) - buildingPartTouchedY);
							invalidate();
						}
					}
				}
				// TODO gebouw ghost rond slepen als er op gedrukt is.(verander de game.queuedBuildingX en
				// game.queuedBuildingY
				// om op een andereplek te tekenen.
			}
			else if (game.isBuildInfrastructure())
			{
				if (touched)
				{
					if (overFieldX((int) e.getX()) < tilesInWidth && overFieldY((int) e.getY()) < tilesInHeight
						&& overFieldX((int) e.getX()) >= 0 && overFieldY((int) e.getY()) >= 0)
					{
						game.queuedBuildingX = overFieldX((int) e.getX());
						game.queuedBuildingY = overFieldY((int) e.getY());
						invalidate();
					}
				}
			}
			else
			{
				// als het verschil met de eerste positie groter is al 20 dan beweegt het beeld 1 stap
				if (e.getX() > fingerdownX + 20)
				{
					if (game.getViewCursorX() < game.getField().length - tilesInWidth)
					{
						game.setViewCursorX(game.getViewCursorX() + 1);
					}
				}
				else if (e.getX() < fingerdownX - 20)
				{
					if (game.getViewCursorX() != 0)
					{
						game.setViewCursorX(game.getViewCursorX() - 1);
					}
				}
				else if (e.getY() > fingerdownY + 20)
				{
					if (game.getViewCursorY() < game.getField()[0].length - tilesInHeight)
					{
						game.setViewCursorY(game.getViewCursorY() + 1);
					}
				}
				else if (e.getY() < fingerdownY - 20)
				{
					if (game.getViewCursorY() != 0)
					{
						game.setViewCursorY(game.getViewCursorY() - 1);
					}
				}
			}
		}
		if (e.getAction() == MotionEvent.ACTION_UP)
		{
			if (overFieldX((int) fingerdownX) < fieldtoview.length
				&& overFieldY((int) fingerdownY) < fieldtoview[0].length &&
				overFieldX((int) fingerdownX) >= 0 && overFieldY((int) fingerdownY) >= 0)
			{
				if (overFieldX((int) e.getX()) < fieldtoview.length
					&& overFieldY((int) e.getY()) < fieldtoview[0].length)
				{
					if (overFieldX((int) e.getX()) == overFieldX((int) fingerdownX)
						&& overFieldY((int) e.getY()) == overFieldY((int) fingerdownY))
						if (fieldtoview[overFieldX((int) fingerdownX)][overFieldY((int) fingerdownY)].getClass() != Tile.class
							|| fieldtoview[overFieldX((int) fingerdownX)][overFieldY((int) fingerdownY)].getClass()
								!= Tile.class)
						{
							GameScreen.tabIsSet = false;
							game.setSelectedTile(fieldtoview[overFieldX((int) fingerdownX)][overFieldY((int) fingerdownY)]);
						}
				}
			}
		}
		return true;
	}

	/**
	 * 
	 * @param XPixel
	 *            aantal pixels vanaf de zijkant
	 * @return het vakje in vanaf links op het veld (hou rekening met de viewcursor)
	 */
	public int overFieldX(int XPixel)
	{

		return (int) ((XPixel - sparespaceX) / tileSize);
	}

	/**
	 * 
	 * @param YPixel
	 *            aantal pixels vanaf bovenkant
	 * @return het vakje in vanaf boven op het veld (hou rekening met de viewcursor)
	 */
	public int overFieldY(int YPixel)
	{

		return (int) ((YPixel - sparespaceY) / tileSize);
	}

	@Override
	public void update(Observable observable, Object data)
	{
		if (data != null)
		{
			if ((Boolean) data == true)
			{
				if (game.getQueuedBuilding() != null)
				{
					buildingMode = true;
					game.queuedBuildingX = 3;
					game.queuedBuildingY = 3;
				}
				if (game.isBuildInfrastructure())
				{
					// game.queuedBuildingX = 4;
					// game.queuedBuildingY = 4;
				}
				else if (game.getQueuedBuilding() == null)
				{
					buildingMode = false;
				}
				postInvalidate();
			}
		}
	}

	// @Override
	// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	// {
	// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	// if (tilesInWidth != 0 && tilesInHeight != 0)
	// {
	// int desiredWidth = tilesInWidth * tileSize;
	// int desiredHeight = tilesInHeight * tileSize;
	//
	// int widthMode = MeasureSpec.getMode(widthMeasureSpec);
	// int widthSize = MeasureSpec.getSize(widthMeasureSpec);
	// int heightMode = MeasureSpec.getMode(heightMeasureSpec);
	// int heightSize = MeasureSpec.getSize(heightMeasureSpec);
	//
	// int width;
	// int height;
	//
	// // Measure Width
	// if (widthMode == MeasureSpec.EXACTLY)
	// {
	// // Must be this size
	// width = widthSize;
	// }
	// else if (widthMode == MeasureSpec.AT_MOST)
	// {
	// // Can't be bigger than...
	// width = Math.min(desiredWidth, widthSize);
	// }
	// else
	// {
	// // Be whatever you want
	// width = desiredWidth;
	// }
	//
	// // Measure Height
	// if (heightMode == MeasureSpec.EXACTLY)
	// {
	// // Must be this size
	// height = heightSize;
	// }
	// else if (heightMode == MeasureSpec.AT_MOST)
	// {
	// // Can't be bigger than...
	// height = Math.min(desiredHeight, heightSize);
	// }
	// else
	// {
	// // Be whatever you want
	//
	// height = desiredHeight;
	// }
	// setMeasuredDimension(width, height);
	// }
	// else
	// {
	// Log.w("GameField", "not set!");
	// super.setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
	// }
	//
	// // MUST CALL THIS
	//
	// }
}
